"""
Case Type   : 操作系统类-文件系统故障
Case Name   : 执行select语句时，备机注入故障文件系统inode资源耗尽
Create At   : 2021/7/19
Owner       : @wan005
Description :
    1、备节点上执行 注入故障文件系统inode资源耗尽
    2、连接数据库select操作
    3、待故障恢复后，再次进行select
    4、运行TPCC
    5、检查数据一致性
    6、恢复环境
Expect      :
    1、故障注入成功
    2、select操作成功，无报错
    3、故障清除成功
    4、成功
    5、数据一致
    6、恢复环境
History     :
    Modified by @wan005 2021/8/17: 增加故障线程等待时间
"""
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node, macro


class ReliabilityFileSystem(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.primary_sh = CommonSH(self.nodes[0])
        self.sta1_sh = CommonSH(self.nodes[1])
        self.constant = Constant()
        self.com = Common()
        self.sta1_root_node = Node(node="Standby1Root")
        self.log.info("setUp-实例化:ok")

        self.log.info("Opengauss_Reliability_OS_File_System_Case003:开始执行")
        self.file_name = macro.DB_INSTANCE_PATH
        self.t_name = "rfile_ideplenish_workmode"
        self.inject_cmd = f"rfile_ideplenish_workmode " \
                          f"(filename, workmode) " \
                          f"values ({self.file_name}, fore)"
        self.clean_cmd = f"rfile_ideplenish_workmode where " \
                         f"filename={self.file_name} and workmode=fore"

    def test_main(self):
        sql = f"drop table if exists {self.t_name} cascade;" \
              f"create table {self.t_name}(id int);" \
              f"insert into {self.t_name} values(generate_series(1,10000));"
        result = self.primary_sh.executDbSql(sql)
        self.log.info(result)
        self.assertNotIn("ERROR", result)

        try:
            self.log.info("步骤2:连接备机执行select")
            sql = f"select pg_sleep(10);" \
                  f"select count(*) from pg_settings;" \
                  f"select count(*) from {self.t_name};" \
                  f"select pg_sleep(20);"
            session1 = ComThread(self.sta1_sh.executDbSql, args=(sql,))
            session1.setDaemon(True)
            session1.start()
            time.sleep(5)

            self.log.info("步骤1:备节点注入文件系统inode资源耗尽故障")
            self.log.info("注入故障")
            session2 = ComThread(self.com.cfe_inject,
                                 args=(self.sta1_root_node,
                                       self.inject_cmd))
            session2.setDaemon(True)
            session2.start()

            session1.join(60)
            result = session1.get_result()
            self.log.info(result)
            self.assertIn("1 row", result)
            self.assertNotIn("ERROR", result)

            session2.join(60 * 50)
            result = session2.get_result()
            self.log.info(result)
            self.assertIn("successful execution", result)

        finally:
            self.log.info("步骤3：清除故障")
            result = self.com.cfe_clean(self.sta1_root_node,
                                        self.clean_cmd)
            self.log.info(result)
            self.assertIn("successful execution", result)

        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        self.assertTrue("Degraded" in db_status or "Normal" in db_status)

        self.log.info("步骤4:运行TPCC")
        result = self.com.startTPCC(Node(node="PrimaryRoot"), macro.TPCC_PATH)
        self.log.info(result)
        self.assertIn(self.constant.TPCC_SUCCESS_MSG, result)

        self.log.info('检查主备是否同步')
        time.sleep(10)
        self.log.info('获取节点数量')
        node_num = self.primary_sh.get_node_num()
        res = self.primary_sh.check_location_consistency("primary", node_num)
        self.assertTrue(res)

        self.log.info('步骤5:检查数据一致性')
        nodes = (Node(self.nodes[0]), Node(self.nodes[1]),
                 Node(self.nodes[2]))
        flag = self.com.check_data_sample_by_all(r'\d', *nodes)
        self.assertTrue(flag)
        table_dict = self.com.format_sql_result(
            self.primary_sh.executDbSql(r'\d'))
        table_name = table_dict.get('Name')
        for name in table_name:
            select_sql = f'select count(*) from {name};'
            flag = self.com.check_data_sample_by_all(select_sql, *nodes)
            self.assertTrue(flag)

    def tearDown(self):
        self.log.info("步骤6:环境清理")
        res = self.com.cfe_clean(self.sta1_root_node, self.clean_cmd)
        self.log.info(res)

        sql = f"drop table if exists {self.t_name} cascade;"
        result = self.primary_sh.executDbSql(sql)
        self.log.info(result)

        self.assertIn("successful execution", res)
        self.log.info("故障已清理")
        self.log.info("Opengauss_Reliability_OS_File_System_Case003:执行完成")
